﻿using System;
using System.Collections.Generic;
using AccessControl.Contracts.Managers;
using AccessControl.Contracts.Models;
using System.Collections.ObjectModel;
using AccessControl.DataManagers;
using System.Threading;
using AccessControl.Gateway.Settings;
using AccessControl.Data.Models;

namespace AccessControl.Gateway.Managers
{
	class EventsManager : IEventsManager
	{
		#region Fields

		private Thread _eventsThread;
		private static int s_SimulationTime = 60000;
		private static EventsManager s_Instance = null;
		private ObservableCollection<IEvent> _events = new ObservableCollection<IEvent>();
		private SynchronizationContext _synchronizationContext = SynchronizationContext.Current;

		#endregion

		#region Private Constructor

		private EventsManager()
		{
			_eventsThread = new Thread(SimulateEvents) { IsBackground = true };
			_eventsThread.Start();
		}

		#endregion

		#region Public Properties

		public static EventsManager Instance
		{
			get 
			{
				lock (typeof(EventsManager))
				{
					if (s_Instance == null)
						s_Instance = new EventsManager();

					return s_Instance;
				}
			}
		}

		#endregion

		#region IEventsManager Members

		public IList<IEvent> Items
		{
			get { return _events; }
		}

		public void Load()
		{
			Items.Clear();
			DataManager.Instance.FillList(Items);
		}

		public void Update(IEvent Event)
		{
			DataManager.Instance.Update(Event);
		}

		#endregion

		#region Private Members

		private void SimulateEvents()
		{
			List<IEvent> events = null;

			while (true)
			{
				if (Session.Instance.LoggedInOperator == null)
				{
					Thread.Sleep(s_SimulationTime);
					continue;
				}

				if (events == null)
				{
					events = new List<IEvent>();
					DataManager.Instance.FillList(events);
				}

				ISensor[] sensors = new ISensor[SensorsSettings.Instance.Items.Count];
				SensorsSettings.Instance.Items.CopyTo(sensors, 0);
				if (sensors.Length == 0)
				{
					Thread.Sleep(s_SimulationTime);
					continue;
				}				

				int idx = new Random().Next(sensors.Length);
				ISensor sensor = sensors[idx];

				/* Create the new event */
				IEvent myEvent = new Event()
				{
					AssociatedSensor = sensor,
					EventTime = DateTime.Now, 
					Id = events.Count + 1,
					Description = string.Format("New {0} event", sensor.Type)
				};

				/* Add to the database */
				 DataManager.Instance.Add(myEvent);
				 events.Add(myEvent);

                /* Now look for the matching entry */
                 foreach (IEntry entry in EntriesManager.Instance.Items)
                 {
                     foreach (ISensor relatedSensor in entry.Sensors)
                     {
                         if (relatedSensor.Id == sensor.Id && entry.Id == sensor.RelatedEntryId)
                         {
                             _synchronizationContext.Post(delegate { entry.Events.Add(myEvent); }, null);
                             break;
                         }
                     }
                 }

                 foreach (IMap map in MapsManager.Instance.Items)
                 {
                     foreach (IMapEntry entry in map.Entries)
                     {
                         foreach (ISensor relatedSensor in entry.Sensors)
                         {
                             if (relatedSensor.Id == sensor.Id && entry.Id == sensor.RelatedEntryId)
                             {
                                 _synchronizationContext.Post(delegate { entry.Events.Add(myEvent); }, null);
                                 break;
                             }
                         }
                     }
                 }

				/* And to the list */
				_synchronizationContext.Post(delegate
				{
					Items.Add(myEvent);
				}, null);

				Thread.Sleep(s_SimulationTime);
			}
		}

		#endregion
	}

}
